#include "delay.h"
#include "freertos.h"
#include "task.h"


static u8 fac_us=0;
static u16 fac_ms=0;	




void SysTick_init()
{
  uint32_t reload;
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);	//选择时钟原，为了跟freertos一致使用改时钟原
	/*
	将芯片内各模块的时钟频率保存在参数RCC_Clocks中，
	包含SYSCLK、HCLK、PCLKx、ADCCLK时钟频率值。
	*/
//	RCC_GetClocksFreq(&RCC_Clocks);
	fac_us = SystemCoreClock/1000000;//计算1us计数多少;
  reload = SystemCoreClock/1000000;
  reload *= 1000000/configTICK_RATE_HZ;//根据configTICK_RATE_HZ设置溢出时间
  
  fac_ms = 1000/configTICK_RATE_HZ; //代表os可以延时的最少单位
  
  SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启sistick中断
  SysTick->LOAD = reload; //每1/configTICK_RATE_HZ中断一次
  SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
}

//us级延时，不会引起rtos调度
void delay_us(u32 nus)
{		
	u32 ticks;//存放延时所需的计数值
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;//自动重装载初值寄存器					  	 
	ticks=nus*fac_us;//存放延时所需的计数值 					 		 	
	told=SysTick->VAL; //当前值寄存器
	//向下计数的
	while(1)
	{
		tnow=SysTick->VAL;//当前值寄存器
		if(tnow!=told)//不相等时
		{	    
			//当前值小于上次的计数值，tcnt累加已经计数器值即told-tnow
			if(tnow<told)tcnt+=told-tnow;
			//当前值大于上次的计数值，tcnt已经reload-tnow为重装载后减了的值再加上told为累加计数器值
			else tcnt+=reload-tnow+told;	    
			
			told=tnow;
			if(tcnt>=ticks)break;//累加值大于延时要求值
		}  
	};								    
}


//ms级延时会引起rtos调度
//nms：0~65535
void delay_ms(uint32_t nms)
{		 						   
   if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
   {
    if(nms>=fac_ms)
    {
      vTaskDelay(nms/fac_ms);
    }
    nms%=fac_ms;
   }
   delay_us((uint32_t)(nms*1000));
}


//延时nms，不会引起任务调度
//nms：0~65535
void delay_xms(u32 nms)
{
  u32 i;
  for(i=0;i<nms;i++)delay_us(1000);
}

